//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Windows.Media;
using OpenLS.Core.Serialization;
using OpenLS.Drawing.Internals;

namespace OpenLS.Drawing
{
    public class LineProperties : IOfficeXmlSerializable, INotifyPropertyChanged, IOfficeXmlSerializableAs
    {
        private CompoundLine _compoundLine;
        private LineEndProperties _headEnd;
        private LineCap _lineCap;
        private LineDashProperties _lineDashProperties;
        private LineFillProperties _lineFillProperties;
        private LineJoinProperties _lineJoinProperties;
        private PenAlignment _penAlignment;
        private LineEndProperties _tailEnd;


        private double? _width;

        public LineCap LineCap
        {
            get { return _lineCap; }
            set
            {
                _lineCap = value;
                notifyPropertyChanged("LineCap");
            }
        }

        public double? Width
        {
            get { return _width; }
            set
            {
                if (value != null && value.Value
                    < 0)
                    throw new ArgumentException("value");
                _width = value;
                notifyPropertyChanged("Width");
            }
        }


        public LineFillProperties LineFillProperties
        {
            get { return _lineFillProperties; }
            set
            {
                _lineFillProperties = value;
                notifyPropertyChanged("LineFillProperties");
            }
        }

        public LineDashProperties LineDashProperties
        {
            get { return _lineDashProperties; }
            set
            {
                _lineDashProperties = value;
                notifyPropertyChanged("LineDashProperties");
            }
        }

        public LineJoinProperties LineJoinProperties
        {
            get { return _lineJoinProperties; }
            set
            {
                _lineJoinProperties = value;
                notifyPropertyChanged("LineJoinProperties");
            }
        }

        public LineEndProperties HeadEnd
        {
            get { return _headEnd; }
            set
            {
                _headEnd = value;
                notifyPropertyChanged("HeadEnd");
            }
        }

        public LineEndProperties TailEnd
        {
            get { return _tailEnd; }
            set
            {
                _tailEnd = value;
                notifyPropertyChanged("TailEnd");
            }
        }

        public CompoundLine CompoundLine
        {
            get { return _compoundLine; }
            set
            {
                _compoundLine = value;
                notifyPropertyChanged("CompoundLine");
            }
        }

        public PenAlignment PenAlignment
        {
            get { return _penAlignment; }
            set
            {
                _penAlignment = value;
                notifyPropertyChanged("PenAlignment");
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IOfficeXmlSerializable Members

        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            ReadXmlAs("ln",context);
            
        }

        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            WriteXmlAs("ln", context);
        }

        #endregion

        public Brush Stroke(ColorScheme colorScheme)
        {

            {
                if (LineFillProperties != null)
                    return LineFillProperties.ToBrush(colorScheme);
                return null;
            }
        }

        private void notifyPropertyChanged(string propertyName)
        {
            Contract.Requires(GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null);
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        public void ReadXmlAs(string name, ReadContext context)
        {
            using (var c = context.Read(name))
            {
                long? l = c.GetOptionalInteger64("w");
                if (l != null)
                    Width = EmuConverter.FromEmu(l.Value);
                LineCap = c.GetOptionalEnum("cap", LineCap.Flat);
                CompoundLine = c.GetOptionalEnum("cmpd", CompoundLine.Single);
                PenAlignment = c.GetOptionalEnum("algn", PenAlignment.Center);
                LineFillProperties = Drawing.LineFillProperties.ReadOptionalLineFillProperties(c);
                LineDashProperties = LineDashProperties.ReadDash(c);
                LineJoinProperties = LineJoinProperties.ReadJoin(c);
                HeadEnd = c.ReadOptionalElementAs<LineEndProperties>("headEnd");
                TailEnd = c.ReadOptionalElementAs<LineEndProperties>("tailEnd");
                c.WarnIf("ext");
            }

        }

        public void WriteXmlAs(string name, WriteContext context)
        {
            using (WriteContext c = context.Write(name))
            {
                if (Width != null)
                    c.SetInteger64("w", EmuConverter.ToEmu(Width.Value));
                c.SetEnum("cap", LineCap);
                c.SetEnum("cmpd", CompoundLine);
                c.SetEnum("algn", PenAlignment);
                c.WriteOptionalElement(LineFillProperties);
                c.WriteOptionalElement(LineDashProperties);
                c.WriteOptionalElement(LineJoinProperties);
                c.WriteOptionalElementAs(HeadEnd, "headEnd");
                c.WriteOptionalElementAs(TailEnd, "tailEnd");
            }
        }
    }
}